package com.attendance.www.hr.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import com.attendance.www.hr.beans.AttendanceBean;
import com.attendance.www.hr.beans.AttendanceDataBean;
import com.attendance.www.hr.beans.AttendancePageBean;
import com.attendance.www.hr.beans.LactationBean;
import com.attendance.www.hr.beans.ReportAttendanceParam;
import com.attendance.www.hr.beans.RequestSelectBean;
import com.attendance.www.hr.constant.AppConstant;
import com.attendance.www.hr.dao.mapper.ApprovalRecordMapper;
import com.attendance.www.hr.dao.mapper.AttachmentMapper;
import com.attendance.www.hr.dao.mapper.AttendanceExtMapper;
import com.attendance.www.hr.dao.mapper.AttendanceMapper;
import com.attendance.www.hr.dao.mapper.DictionaryMapper;
import com.attendance.www.hr.dao.mapper.EmployeeExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSchedulMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSpecialMapper;
import com.attendance.www.hr.dao.mapper.LactationExtMapper;
import com.attendance.www.hr.dao.mapper.PunchTimeMapper;
import com.attendance.www.hr.dao.mapper.RequestMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveExtMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveMapper;
import com.attendance.www.hr.dao.mapper.SchedulDayMapper;
import com.attendance.www.hr.dao.mapper.SpecialMapper;
import com.attendance.www.hr.entitys.ApprovalRecordExample;
import com.attendance.www.hr.entitys.Attachment;
import com.attendance.www.hr.entitys.Attendance;
import com.attendance.www.hr.entitys.AttendanceExample;
import com.attendance.www.hr.entitys.Dictionary;
import com.attendance.www.hr.entitys.DictionaryExample;
import com.attendance.www.hr.entitys.Employee;
import com.attendance.www.hr.entitys.EmployeeExample;
import com.attendance.www.hr.entitys.EmployeeRole;
import com.attendance.www.hr.entitys.EmployeeRoleExample;
import com.attendance.www.hr.entitys.EmployeeSchedul;
import com.attendance.www.hr.entitys.EmployeeSchedulExample;
import com.attendance.www.hr.entitys.EmployeeSpecialExample;
import com.attendance.www.hr.entitys.EmployeeSpecialKey;
import com.attendance.www.hr.entitys.PunchTime;
import com.attendance.www.hr.entitys.PunchTimeExample;
import com.attendance.www.hr.entitys.Request;
import com.attendance.www.hr.entitys.RequestExample;
import com.attendance.www.hr.entitys.Retroactive;
import com.attendance.www.hr.entitys.RetroactiveExample;
import com.attendance.www.hr.entitys.SchedulDayExample;
import com.attendance.www.hr.entitys.SchedulDayKey;
import com.attendance.www.hr.entitys.Special;
import com.attendance.www.hr.entitys.SpecialExample;
import com.attendance.www.hr.exception.ResultFaultException;
import com.attendance.www.hr.service.IApprovalService;
import com.attendance.www.hr.service.IAttendanceService;
import com.attendance.www.hr.service.IBpmService;
import com.attendance.www.hr.service.IReportService;
import com.attendance.www.hr.utils.FactorialUtils;
import com.attendance.www.hr.utils.TimeUtils;

@Service
public class AttendanceServiceImpl implements IAttendanceService {

	@Resource
	private AttendanceExtMapper attendanceExtDao;
	@Resource
	private AttachmentMapper attachmentDao;
	@Resource
	private EmployeeMapper employeeDao;
	@Resource
	private EmployeeExtMapper employeeExtDao;
	@Resource
	private RetroactiveMapper retroactiveDao;
	@Resource
	private RetroactiveExtMapper retroactiveExtDao;
	@Resource
	private ApprovalRecordMapper approvalRecordDao;
	@Resource
	private AttendanceMapper attendanceDao;
	@Resource
	private RequestMapper requestDao;
	@Resource
	private SpecialMapper specialDao;
	@Resource
	private PunchTimeMapper punchTimeDao;
	@Resource
	private EmployeeSchedulMapper employeeSchedulDao;
	@Resource
	private SchedulDayMapper schedulDayDao;
	@Resource
	private DictionaryMapper dictionaryDao;
	@Resource
	private LactationExtMapper lactationExtDao;
	@Resource
	private EmployeeSpecialMapper employeeSpecialDao;
	@Resource
	private EmployeeRoleMapper employeeRoleDao;
	@Resource
	private EmployeeRoleExtMapper employeeRoleExtDao;
	@Resource
	private IReportService reportService;
	@Resource
	private IApprovalService approvalService;
	@Resource
	private IBpmService bpmService;
	

	/**
	 * 分等级账户等级获取， PrivilegeGroupId=4为admin账户，可以直接查询全部
	 * PrivilegeGroupId=3为hr账户，可以查询所分配公司
	 * PrivilegeGroupId=2为审批人账户，可以查询所属下属岗位，可多岗位一起查询
	 * PrivilegeGroupId=1为员工账户，可以查询自己的考勤 可根据公司，部门，员工名称，员工级别，考勤状态，补签状态，审核状态，签到日期，签退日期
	 * 来获取员工号，中午名，英文名，签到日期，上班日期，末班签退，考勤状态，补签状态，补签状态，审批状态，补签时间，特殊考勤时间，备注
	 */
	@Override
	public AttendancePageBean getAttendanceList(AttendanceBean attendanceBean, Integer startNum, Integer pageCount,
			Integer employeeId, Boolean type) {
		AttendancePageBean attendancePageBean = new AttendancePageBean();
		List<AttendanceBean> attendanceBeanList = new ArrayList<AttendanceBean>();
		int pageTotal = 0;
		// 获取系统当前时间
		List<Integer> employeeIdList = new ArrayList<Integer>();
		if (attendanceBean.getPrivilegeGroupId() == 5) {
			if (attendanceBean.isRoleType()) {
				// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
				List<Integer> roleListId = attendanceExtDao.getRolrByEmployeeId(attendanceBean, employeeId);
				if (roleListId.size() > 0) {
					employeeIdList = attendanceExtDao.getEmployeeIdListByRoleId(attendanceBean, employeeId, roleListId);
					if (employeeIdList.size() == 0) {
						attendancePageBean.setAttendanceBeanList(attendanceBeanList);
						attendancePageBean.setPageTotal(0);
						return attendancePageBean;
					}
					attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum,
							pageCount, type);
					pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
				}
			} else {
				employeeIdList = attendanceExtDao.getEmployeeByCorporation(attendanceBean, employeeId);
				if (employeeIdList.size() == 0) {
					attendancePageBean.setAttendanceBeanList(attendanceBeanList);
					attendancePageBean.setPageTotal(0);
					return attendancePageBean;
				}
				attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum,
						pageCount, type);
				pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
			}
		}
		// 判断是否为分公司HR权限
		else if (attendanceBean.getPrivilegeGroupId() == 4) {
			// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
			employeeIdList = attendanceExtDao.getEmployeeByCorporation(attendanceBean, employeeId);
			if (employeeIdList.size() == 0) {
				attendancePageBean.setAttendanceBeanList(attendanceBeanList);
				attendancePageBean.setPageTotal(0);
				return attendancePageBean;
			}
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
		}
		// 判断审批人
		else if (attendanceBean.getPrivilegeGroupId() == 3) {
			employeeIdList=new ArrayList<Integer>();
			EmployeeRoleExample employeeRoleExample=new EmployeeRoleExample();
			employeeRoleExample.createCriteria().andEmployeeIdEqualTo(employeeId);
			List<EmployeeRole> employeeRoleList=employeeRoleDao.selectByExample(employeeRoleExample);
			for(int i=0;i<employeeRoleList.size();i++) {
				employeeIdList.addAll(employeeRoleExtDao.selectEmployeeRoleGetEmployeeIdByRoleId(employeeRoleList.get(i).getRoleId()));
			}
			employeeIdList=FactorialUtils.filterEmployeeId(employeeIdList);
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum,pageCount, type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
			
			/****原版本-根据岗位ID查询员工ID集合****/
			/*// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
			List<Integer> roleListId = attendanceExtDao.getRolrByEmployeeId(attendanceBean, employeeId);
			if (roleListId.size() > 0) {
				employeeIdList = attendanceExtDao.getEmployeeIdListByRoleId(attendanceBean, employeeId, roleListId);
				if (employeeIdList.size() == 0) {
					attendancePageBean.setAttendanceBeanList(attendanceBeanList);
					attendancePageBean.setPageTotal(0);
					return attendancePageBean;
				}
				attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum,
						pageCount, type);
				pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
			} else {
				attendanceBean.setEmployeeId(employeeId);
			}*/
			/************************************/
		}
		// 判断普通用户
		else if (attendanceBean.getPrivilegeGroupId() == 2) {
			attendanceBean.setEmployeeId(employeeId);
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
		} else {
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
		}

		// 循环遍历是否有申请信息
		for (int i = 0; i < attendanceBeanList.size(); i++) {
			AttendanceBean ab = attendanceBeanList.get(i);
			ab.setAttendanceStateType(false);
			// 是否有审批通过补签
			/*
			 * if(ab.getFlgRetroactive()>0){ ab.setAttendanceStateType(true); }
			 */
			// 是否有申请同意
			if (ab.getFlgRequest() > 0) {
				ab.setAttendanceStateType(true);
			}
			// 是否有上班补签审批中
			if (ab.getFlgStart() > 0) {
				ab.setRetroactiveStartType(true);
			} else {
				ab.setRetroactiveStartType(false);
			}
			// 是否有末班补签审批中
			if (ab.getFlgEnd() > 0) {
				ab.setRetroactiveEndType(true);
			} else {
				ab.setRetroactiveEndType(false);
			}
		}
		attendancePageBean.setAttendanceBeanList(attendanceBeanList);
		attendancePageBean.setPageTotal(pageTotal);
		return attendancePageBean;
	}

	/**
	 * 获取个人的应出勤时间，实际出勤时间，迟到，早退，旷工，补签---update_zx
	 */
	@Override
	public AttendanceDataBean getAttendanceData(AttendanceBean attendanceBean, Integer employeeId) {
		attendanceBean.setEmployeeId(employeeId);
		AttendanceDataBean attendanceData = new AttendanceDataBean();
		ReportAttendanceParam paramBean = new ReportAttendanceParam();
		paramBean.setBeginDate(attendanceBean.getAttendanceDateStart());
		paramBean.setEndDate(attendanceBean.getAttendanceDateEnd());
		List<Integer> employeeIds = new ArrayList<>();
		employeeIds.add(employeeId);
		reportService.getAbsentCount(paramBean, employeeIds);

		// 应出勤工时
		attendanceData.setShouldAttendanceTime(attendanceExtDao.getShouldTime(attendanceBean));
		// 实际出勤时长
		attendanceData.setAttendanceTime(attendanceExtDao.getActualTime(attendanceBean));
		// 加班时长
		attendanceData.setOverTime(attendanceExtDao.getOvertime(attendanceBean));
		// 迟到
		attendanceData.setLateNumber(reportService.getLateCount(paramBean, employeeIds).get(employeeId));
		// 早退
		attendanceData.setLeaveEarlyNumber(reportService.getLeaveEarlyCount(paramBean, employeeIds).get(employeeId));
		// 取得员工旷工次数
		attendanceData.setAbsenteeismNumber(reportService.getAbsentCount(paramBean, employeeIds).get(employeeId));
		// 补签
		attendanceData.setRetroactiveNumber(reportService.getRetroactiveCount(paramBean, employeeIds).get(employeeId));
		// 请假
		RequestExample requestExample = new RequestExample();
		List<Integer> requestTypeList = new ArrayList<>();
		requestTypeList.add(7);
		requestTypeList.add(8);
		requestTypeList.add(9);
		requestExample.createCriteria().andEmployeeIdEqualTo(employeeId)
				.andStartDateBetween(attendanceBean.getAttendanceDateStart(), attendanceBean.getAttendanceDateEnd())
				.andRequestTypeNotIn(requestTypeList)
				.andApprovalStateEqualTo(2);
		List<Request> requestList = requestDao.selectByExample(requestExample);
		attendanceData.setLeaveNumber(requestList.size());
		return attendanceData;
	}

	/**
	 * 考勤信息导入
	 * 
	 * @param attachmentId
	 * @return
	 */
	@Override
	public List<String> importAttendance(Integer attachmentId) {
		List<String> successList = new ArrayList<String>();
		// 查询附件表获取路径地址
		Attachment attachment = attachmentDao.selectByPrimaryKey(attachmentId);
		// 设置文件路径
		String pathName = attachment.getUrl().replace(AppConstant.UPLOAD_RESOURCE, AppConstant.SAVE_FILE_REPOSITORY);
		File file = new File(pathName);
		Workbook work = null;
		if (file.exists()) {
			try {
				InputStream inputStream = new FileInputStream(file);
				if (pathName.matches("^.+\\.(?i)(xls)$")) {
					work = new HSSFWorkbook(inputStream);
				} else if (pathName.matches("^.+\\.(?i)(xlsx)$")) {
					work = new XSSFWorkbook(inputStream);
				}
			} catch (Exception ex) {
				throw new ResultFaultException("0_00003");
			}
		} else {
			throw new ResultFaultException("0_00003");
		}
		if (work == null) {
			throw new ResultFaultException("0_00003");
		}

		if (work != null) {
			List<String> attendanceList = addAttendance(work);
			successList.addAll(attendanceList);
		}
		return successList;
	}

	/**
	 * 增加考勤信息
	 * 
	 * @param work
	 * @return
	 */
	private List<String> addAttendance(Workbook work) {
		// 获取系统当前时间
		Date currentDate = new Date();
		// 设置保存考勤导入日期，用于处理当天未打卡的员工记录
		Map<Date, Date> attendanceDateMap = new HashMap<Date, Date>();
		// 人员ID
		List<Integer> employeeIdList = new ArrayList<Integer>();
		// 根据当前日期，的前一个月
		Calendar cStrat = Calendar.getInstance();
		cStrat.setTime(new Date());
		cStrat.add(Calendar.MONTH, -1);
		// 根据当前日期，的后一个月
		Calendar cEnd = Calendar.getInstance();
		cEnd.setTime(new Date());
		cEnd.add(Calendar.MONTH, 1);
		// 查询员工
		List<Employee> employeeList = employeeExtDao.getEmployeeList(currentDate, currentDate);
		Map<String, Employee> employeeMap = new HashMap<String, Employee>();
		Map<Integer, Employee> employeeIdMap = new HashMap<Integer, Employee>();
		for (int ei = 0; ei < employeeList.size(); ei++) {
			employeeMap.put(employeeList.get(ei).getEmployeeNo(), employeeList.get(ei));
			employeeIdMap.put(employeeList.get(ei).getEmployeeId(), employeeList.get(ei));
		}
		// 查询特殊情况
		SpecialExample specialExample = new SpecialExample();
		specialExample.createCriteria().andSpecialDateBetween(cStrat.getTime(), cEnd.getTime());
		Map<Date, List<EmployeeSpecialKey>> specialEmployeeyMap = new HashMap<Date, List<EmployeeSpecialKey>>();
		Map<Integer, Special> specialMap = new HashMap<Integer, Special>();
		// 查询特殊情况
		List<Special> specialList = specialDao.selectByExample(specialExample);
		for (int si = 0; si < specialList.size(); si++) {
			EmployeeSpecialExample employeeSpecialExample = new EmployeeSpecialExample();
			employeeSpecialExample.createCriteria().andSpecialIdEqualTo(specialList.get(si).getSpecialId());
			List<EmployeeSpecialKey> employeeSpecialKeyList = employeeSpecialDao
					.selectByExample(employeeSpecialExample);
			specialEmployeeyMap.put(specialList.get(si).getSpecialDate(), employeeSpecialKeyList);
			specialMap.put(specialList.get(si).getSpecialId(), specialList.get(si));
		}

		// 查询班次情况
		EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
		employeeSchedulExample.setOrderByClause("employee_id asc,from_date desc");
		List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
		List<Integer> swIdList = new ArrayList<Integer>();
		Map<Integer, List<EmployeeSchedul>> employeeSchedulMap = new HashMap<Integer, List<EmployeeSchedul>>();
		for (int ei = 0; ei < employeeSchedulList.size(); ei++) {
			if (employeeSchedulMap.containsKey(employeeSchedulList.get(ei).getEmployeeId())) {
				List<EmployeeSchedul> eList = employeeSchedulMap.get(employeeSchedulList.get(ei).getEmployeeId());
				eList.add(employeeSchedulList.get(ei));
				employeeSchedulMap.put(employeeSchedulList.get(ei).getEmployeeId(), eList);
			} else {
				List<EmployeeSchedul> eList = new ArrayList<EmployeeSchedul>();
				eList.add(employeeSchedulList.get(ei));
				employeeSchedulMap.put(employeeSchedulList.get(ei).getEmployeeId(), eList);
			}
			swIdList.add(employeeSchedulList.get(ei).getSwId());
		}
		// 查询考勤打卡
		List<PunchTime> punchTimeList = punchTimeDao.selectByExample(new PunchTimeExample());
		Map<Integer, PunchTime> punchTimeMap = new HashMap<Integer, PunchTime>();
		for (int pi = 0; pi < punchTimeList.size(); pi++) {
			punchTimeMap.put(punchTimeList.get(pi).getPunchTimeId(), punchTimeList.get(pi));
		}
		
		//设置请假类型
		List<Integer> requestTypeList = new ArrayList<Integer>();
		requestTypeList.add(0);
		requestTypeList.add(1);
		requestTypeList.add(2);
		requestTypeList.add(3);
		requestTypeList.add(4);
		requestTypeList.add(5);
		requestTypeList.add(6);
		requestTypeList.add(8);
		requestTypeList.add(9);
		requestTypeList.add(11);
		requestTypeList.add(12);
		requestTypeList.add(13);

		// 查询申请表-审批同意-申请日
		RequestExample requestExample = new RequestExample();
		requestExample.createCriteria().andApprovalStateEqualTo(2).andRequestTypeIn(requestTypeList)
				.andRequestDateBetween(cStrat.getTime(), cEnd.getTime());
		List<Request> requestList = requestDao.selectByExample(requestExample);
		Map<Integer, List<Request>> requestMap = new HashMap<Integer, List<Request>>();
		for (int ei = 0; ei < requestList.size(); ei++) {
			if (requestMap.containsKey(requestList.get(ei).getEmployeeId())) {
				List<Request> eList = requestMap.get(requestList.get(ei).getEmployeeId());
				eList.add(requestList.get(ei));
				requestMap.put(requestList.get(ei).getEmployeeId(), eList);
			} else {
				List<Request> eList = new ArrayList<Request>();
				eList.add(requestList.get(ei));
				requestMap.put(requestList.get(ei).getEmployeeId(), eList);
			}
		}
		// 查询休假类型
		DictionaryExample dictionaryExample = new DictionaryExample();
		dictionaryExample.createCriteria().andDicClsEqualTo("5").andStatusEqualTo("1");
		List<Dictionary> dictionaryList = dictionaryDao.selectByExample(dictionaryExample);
		Map<String, Dictionary> dictionaryMap = new HashMap<String, Dictionary>();
		for (int di = 0; di < dictionaryList.size(); di++) {
			dictionaryMap.put(dictionaryList.get(di).getDicCd(), dictionaryList.get(di));
		}
		// 查询哺乳假期
		List<LactationBean> lactationBeanList = lactationExtDao.getLactationEmployeeList(currentDate, currentDate,null);
		Map<String, List<LactationBean>> lactationMap = new HashMap<String, List<LactationBean>>();
		for (int li = 0; li < lactationBeanList.size(); li++) {
			if (lactationMap.containsKey(lactationBeanList.get(li).getEmployeeNo())) {
				List<LactationBean> lList = lactationMap.get(lactationBeanList.get(li).getEmployeeNo());
				lList.add(lactationBeanList.get(li));
				lactationMap.put(lactationBeanList.get(li).getEmployeeNo(), lList);
			} else {
				List<LactationBean> lList = new ArrayList<LactationBean>();
				lList.add(lactationBeanList.get(li));
				lactationMap.put(lactationBeanList.get(li).getEmployeeNo(), lList);
			}
		}
		// 查询班次日期
		SchedulDayExample schedulDayExample = new SchedulDayExample();
		schedulDayExample.createCriteria().andSwIdIn(swIdList);
		// .andSdDateBetween(cStrat.getTime(), cEnd.getTime());
		List<SchedulDayKey> schedulDayKeyList = schedulDayDao.selectByExample(schedulDayExample);
		Map<Integer, List<SchedulDayKey>> schedulDayKeyMap = new HashMap<Integer, List<SchedulDayKey>>();
		for (int si = 0; si < schedulDayKeyList.size(); si++) {
			if (schedulDayKeyMap.containsKey(schedulDayKeyList.get(si).getSwId())) {
				List<SchedulDayKey> lList = schedulDayKeyMap.get(schedulDayKeyList.get(si).getSwId());
				lList.add(schedulDayKeyList.get(si));
				schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
			} else {
				List<SchedulDayKey> lList = new ArrayList<SchedulDayKey>();
				lList.add(schedulDayKeyList.get(si));
				schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
			}
		}
		
		
		// 设置提示信息
		List<String> successList = new ArrayList<String>();
		// 记录重新计算人员
		List<Integer> requestEmployeeIdList = new ArrayList<Integer>();
		Map<Integer, Integer> requestEmployeeIdMap = new HashMap<Integer, Integer>();

		// 获取工作表的数量
		int sheetNum = work.getNumberOfSheets();
		// 遍历工作表 找出要导入的Excel表
		for (int m = 0; m < sheetNum; m++) {
			Sheet sh = work.getSheetAt(m);
			if (sh.getSheetName().equals("考勤信息")) {
				Sheet sheet = work.getSheetAt(m);
				List<String> errorMsgList = new ArrayList<String>();// 创建错误信息列表
				// 扫描Excel每行的每个单元格
				for (int i = 1; i <= sheet.getLastRowNum(); i++) {
					Attendance attendance = new Attendance();// 创建考勤对象
					// 考勤打卡ID
					Integer punchTimeId = null;
					StringBuilder str = new StringBuilder("第" + (i + 1) + "行");
					Row row = sheet.getRow(i);
					// 如果一整行为空则忽略此行继续遍历
					if (row == null) {
						continue;
					}
					// 遍历某一行的所有列，如果此行每列都为空则跳过继续下一行
					boolean isNull = true;
					for (int c = 0; c < row.getLastCellNum(); c++) {
						if (row.getCell(c) == null || StringUtils.isBlank(row.getCell(c).toString())) {
							continue;
						} else {
							isNull = false;
						}
					}
					if (isNull) {
						continue;
					}

					String employeeNo = null;
					LactationBean lactationBean = null;
					boolean punchTimeType = true; // 控制是否显示无班次开关
					boolean lactationType = false; // 是否休息哺乳假
					long startTimeHours = 0;
					boolean weekendType = false; // 周末上班状态
					Integer swId = null; // 班次ID

					// 判断第一列员工号
					if (row.getCell(0) != null && StringUtils.isNotBlank(row.getCell(0).toString())) {
						// 判断是否为数字
						if (row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
							employeeNo = new BigDecimal(row.getCell(0).getNumericCellValue()).intValue() + "";
						} else {
							employeeNo = row.getCell(0).toString();
						}
						if (employeeNo.length() <= 4) {
							employeeNo = "0" + employeeNo;
						}
						// 判断员工号是否存在-首位补0
						if (employeeMap.containsKey(employeeNo)) {
							// 设置员工ID
							attendance.setEmployeeId(employeeMap.get(employeeNo).getEmployeeId());
							boolean type = true;
							for (int l = 0; l < employeeIdList.size(); l++) {
								if (employeeIdList.get(l) == attendance.getEmployeeId()) {
									type = false;
									break;
								}
							}
							if (type) {
								employeeIdList.add(attendance.getEmployeeId());
							}
						} else {
							str.append("员工号不存在,");
						}
					} else {
						str.append("员工号不能为空,");
					}

					// 判断第二列日期
					if (row.getCell(2) != null && StringUtils.isNotBlank(row.getCell(2).toString())) {
						Date attendanceDate = new Date();
						// 判断是否为字符串或是日期类型
						SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");// 可以方便地修改日期格式
						try {
							// 判断是否为字符串
							if (row.getCell(2).getCellType() == HSSFCell.CELL_TYPE_STRING) {
								attendanceDate = dateFormat.parse(row.getCell(2).toString());
							}
							// 判断是否为日期
							else if (HSSFDateUtil.isCellDateFormatted(row.getCell(2))) {
								attendanceDate = row.getCell(2).getDateCellValue();
							}
							// 记录导入不同的日期，将用于处理未打卡的人员使用
							if (!attendanceDateMap.containsKey(attendanceDate)) {
								attendanceDateMap.put(attendanceDate, attendanceDate);
							}
							// 设置签到日期
							attendance.setAttendanceDate(attendanceDate);
							// 比较日期是否等于特殊情况日期
							if (specialEmployeeyMap.containsKey(attendanceDate)) {
								// 比较导入员工是否在特殊情况设置中
								List<EmployeeSpecialKey> employeeSpecialKeyList = specialEmployeeyMap
										.get(attendanceDate);
								for (int eik = 0; eik < employeeSpecialKeyList.size(); eik++) {
									if (employeeSpecialKeyList.get(eik).getEmployeeId()
											.equals(attendance.getEmployeeId())) {
										attendance.setSpecialId(employeeSpecialKeyList.get(eik).getSpecialId());
										// 获取特殊情况信息
										Special special = specialMap
												.get(employeeSpecialKeyList.get(eik).getSpecialId());
										// 设置备注说明
										String description = "系统管理员设置特殊情况：" + special.getSpecialName();
										if (special.getDescription() != null) {
											description += "，说明(" + special.getDescription() + ")";
										}
										attendance.setDescription(description);
										break;
									}
								}
							}
							// 处理班次
							if (attendance.getEmployeeId() != null) {
								// 判断员工和班次关系是否存在
								if (employeeSchedulMap.containsKey(attendance.getEmployeeId())) {
									// 判断员工所属日期范围
									List<EmployeeSchedul> eList = employeeSchedulMap.get(attendance.getEmployeeId());
									// 循环判断日期范围是否匹配
									for (int ei = 0; ei < eList.size(); ei++) {
										EmployeeSchedul employeeSchedul = eList.get(ei);
										// 验证日期是否在区间内
										if (dateCalendar(attendanceDate, employeeSchedul.getFromDate(),
												employeeSchedul.getThruDate())) {
											punchTimeId = employeeSchedul.getPunchTimeId();
											swId = employeeSchedul.getSwId();
											break;
										}
									}
								}
							}

							boolean swIdType = false;
							// 遍历班次日期
							if (swId != null) {
								if (schedulDayKeyMap.containsKey(swId)) {
									List<SchedulDayKey> lList = schedulDayKeyMap.get(swId);
									// 循环判断是否在班次日期中
									for (int isl = 0; isl < lList.size(); isl++) {
										// 如果日期相等，表示为上班
										if (lList.get(isl).getSdDate().equals(attendance.getAttendanceDate())) {
											swIdType = true;
											break;
										} else {
											swIdType = false;
										}
									}
								}
							}

							Calendar cal = Calendar.getInstance();
							cal.setTime(attendance.getAttendanceDate());
							// 判断是为周末上班
							if (swIdType == false) { // isWeekend(cal) &&
								// 如果为周末上班，不计算考勤状态
								weekendType = true;
								// 休息日
								attendance.setAttendanceState(9);
							}
						} catch (Exception e) {
							str.append("日期格式不正确,");
							punchTimeType = false;
						}
					} else {
						str.append("日期不能为空,");
						punchTimeType = false;
					}

					// 计算应出勤工时数
					if (punchTimeId != null) {
						if (punchTimeMap.containsKey(punchTimeId)) {
							PunchTime punchTime = punchTimeMap.get(punchTimeId);
							// 计算分钟
							long minutes = minutesTimeCalendar(punchTime.getEndToTime(), punchTime.getStartToTime());
							BigDecimal mia;
							BigDecimal mib;
							mia = new BigDecimal(minutes);
							mib = new BigDecimal(60);
							attendance.setAttendenceHours(
									mia.divide(mib, 1, RoundingMode.HALF_UP).subtract(new BigDecimal(1)));
						}

						// 判断四列签到时间
						if (row.getCell(4) != null && StringUtils.isNotBlank(row.getCell(4).toString())) {
							String startTime = null;
							// 判断是否为日期类型
							if (row.getCell(4).getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
								// 判断是否为字符串或是日期类型
								SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");// 可以方便地修改日期格式
								startTime = dateFormat.format(row.getCell(4).getDateCellValue());
							} else {
								startTime = row.getCell(4).toString();
							}
							// 设置原有打卡时间
							attendance.setOriginalStartTime(startTime);
							// 设置打卡时间
							attendance.setStartTime(startTime);

							if (weekendType == false) {
								// 设置正常
								attendance.setAttendanceState(1);

								// 第一步，判断是否为特殊情况
								if (attendance.getSpecialId() != null) {
									Special special = specialMap.get(attendance.getSpecialId());
									if(special.getStartTime()!=null){
										// 判断如果打卡签到时间，小于特殊情况时间，使用打卡签到时间
										if (timeCalendar(startTime, special.getStartTime())) {
											// 设置打卡时间
											attendance.setStartTime(startTime);
										} else {
											// 设置特殊情况开始时间
											attendance.setStartTime(special.getStartTime());
										}
									}else{
										// 设置打卡时间
										attendance.setStartTime(startTime);
									}
								} else {
									// 设置打卡时间
									attendance.setStartTime(startTime);
									// 处理是否迟到
									if (punchTimeMap.containsKey(punchTimeId)) {
										// 获取考勤打卡时间-早上签到时间
										PunchTime punchTime = punchTimeMap.get(punchTimeId);
										// 判断打卡时间小于考勤打卡时间为提前打卡为正常
										if (timeCalendar(startTime, punchTime.getStartFromTime())) {
											// 设置考勤状态-正常
											attendance.setAttendanceState(1);
										}
										// 判断早上打卡时间是否在考勤打卡时间区间内为正常打卡
										else if (timeCalendar(startTime, punchTime.getStartFromTime(),
												punchTime.getStartToTime())) {
											// 设置考勤状态-正常
											attendance.setAttendanceState(1);
										} else {
											// 判断是否迟到
											long minutes = minutesTimeCalendar(startTime, punchTime.getStartToTime());
											if (minutes <= punchTime.getStartInterval()) {
												// 迟到
												attendance.setAttendanceState(2);
												// 设置迟到时间分钟
												attendance.setLateHours(new BigDecimal(minutes));
											} else {
												// 旷工
												attendance.setAttendanceState(5);
											}
											// 判断员工号是否存在-哺乳假期,状态不等于1
											if (lactationMap.containsKey(employeeNo)
													&& attendance.getAttendanceState() != 1) {
												// 获取对应员工的哺乳假期
												List<LactationBean> lactationList = lactationMap.get(employeeNo);
												// 循环判断日期是否在，哺乳假期范围内
												for (int lai = 0; lai < lactationList.size(); lai++) {
													LactationBean lab = lactationList.get(lai);
													if (dateCalendar(attendance.getAttendanceDate(),
															lab.getHbornStartDate(), lab.getEndDate())) {
														lactationBean = lab;
														break;
													}
												}
												// 查看打开时间是否在范围之内
												if (lactationBean != null) {
													// 当天打开时间减去班次打卡时间
													startTimeHours = minutesTimeCalendar(attendance.getStartTime(),
															punchTime.getStartToTime());
													// 根据哺乳假期小时乘60分钟
													Integer hours = lactationBean.getHours()
															.multiply(new BigDecimal(60)).intValue();
													Integer hMinutes = 0;
													// 判断早上打开时间是否早于班次打卡时间
													if (TimeUtils.differMinutes(punchTime.getStartToTime(),
															attendance.getStartTime()) < hours) {
														hMinutes = TimeUtils.differMinutes(punchTime.getStartToTime(),
																attendance.getStartTime());
													} else {
														// 计算时间
														hMinutes = TimeUtils.differMinutes(punchTime.getStartToTime(),
																attendance.getStartTime()) - hours;
													}
													attendance.setLateHours(new BigDecimal(0));
													attendance.setDescription("早上休哺乳假期");
													lactationType = true;
													if (startTimeHours <= hours) {
														// 正常
														attendance.setAttendanceState(1);
													} else {
														if (hMinutes <= punchTime.getStartInterval()) {
															// 迟到
															attendance.setAttendanceState(2);
															// 设置迟到时间分钟
															attendance.setLateHours(new BigDecimal(hMinutes));
														} else {
															// 旷工
															attendance.setAttendanceState(5);
														}
													}
												}
											}
										}
									} else {
										punchTimeType = false;
										str.append("员工号没有所属班次,");
									}
								}
							}
						} else {
							if (weekendType == false) {
								// 设置考勤状态-缺卡
								attendance.setAttendanceState(5);
							}
						}

						// 判断五列签到日期
						if (row.getCell(5) != null && StringUtils.isNotBlank(row.getCell(5).toString())) {
							String endTime = null;
							// 判断是否为日期类型
							if (row.getCell(5).getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
								// 判断是否为字符串或是日期类型
								SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");// 可以方便地修改日期格式
								endTime = dateFormat.format(row.getCell(5).getDateCellValue());
							} else {
								endTime = row.getCell(5).toString();
							}
							// 设置原有打卡时间
							attendance.setOriginalEndTime(endTime);
							// 设置打卡时间
							attendance.setEndTime(endTime);

							if (weekendType == false) {
								Special special = specialMap.get(attendance.getSpecialId());
								if (special != null) {
									if(special.getEndTime()!=null){
										// 判断如果打卡签到时间，小于特殊情况时间，使用打卡签到时间
										if (timeCalendar(endTime, special.getEndTime())) {
											// 设置打卡时间
											attendance.setEndTime(endTime);
										} else {
											// 设置特殊情况开始时间
											attendance.setEndTime(special.getEndTime());
										}
									}else{
										// 设置打卡时间
										attendance.setEndTime(endTime);
									}
								} else {
									// 设置打卡时间
									attendance.setEndTime(endTime);
									// 处理是否早退
									if (punchTimeMap.containsKey(punchTimeId)) {
										// 获取考勤打卡时间-晚上签退时间
										PunchTime punchTime = punchTimeMap.get(punchTimeId);
										// 判断是否上午休哺乳假
										if (lactationType) {
											// 计算哺乳假时长
											Integer hours = lactationBean.getHours().multiply(new BigDecimal(60))
													.intValue();
											Integer munutes = 0;
											// 午休时间段,计算
											if (punchTime.getRestFromTime() != null
													&& punchTime.getRestToTime() != null) {
												munutes = TimeUtils.differMinutes(punchTime.getRestFromTime(),
														punchTime.getRestToTime());
											}
											// 设置打卡时间
											String startTime = attendance.getStartTime();
											// 判断时长是否为，根据打卡时间减去午休时间+哺乳假休息时间
											long lHours = 0;
											// 判断早上休哺乳假是否减去一小时后，小于8:30，如果小于使用默认班次开始时间
											if ((minutesTimeCalendar(startTime) - hours) < minutesTimeCalendar(
													punchTime.getStartFromTime())) {
												startTime = punchTime.getStartFromTime();
												// 判断时长是否为，根据打卡时间减去午休时间+哺乳假休息时间
												lHours = (TimeUtils.differMinutes(startTime, attendance.getEndTime())
														- munutes);
											} else {
												// 判断时长是否为，根据打卡时间减去午休时间+哺乳假休息时间
												lHours = (TimeUtils.differMinutes(startTime, attendance.getEndTime())
														- munutes) + hours;
											}
											// 判断加班到第二天凌晨打卡，为正常出勤
											DateFormat df = new SimpleDateFormat("HH");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
											Calendar calendar = Calendar.getInstance();
											Integer hour = null;
											try {
												calendar.setTime(df.parse(endTime));
												String hourStr = (new SimpleDateFormat("HH"))
														.format(calendar.getTime());
												if (hourStr != null) {
													hour = Integer.valueOf(hourStr);
												}
											} catch (ParseException e) {
												// TODO Auto-generated catch block
												e.printStackTrace();
											}
											// 判断时间是否为凌晨打卡。0-4点区间
											if (hour != null) {
												if (hour >= 0 && hour <= 4) {
													// 正常上班
													attendance.setAttendanceState(1);
												} else {
													// 根据应出勤天数，计算应下班时间
													BigDecimal attendenceHours = attendance.getAttendenceHours()
															.multiply(new BigDecimal(60));
													// 获取应出勤分钟
													long attendenceHoursTime = attendenceHours.longValue();
													munutes = 0;
													// 午休时间段,计算
													if (punchTime.getRestFromTime() != null
															&& punchTime.getRestToTime() != null) {
														munutes = TimeUtils.differMinutes(punchTime.getRestFromTime(),
																punchTime.getRestToTime());
													}

													// 获取签退分钟
													long endTimeTime = 0;
													if (attendance.getStartTime() != null
															&& attendance.getEndTime() != null) {
														endTimeTime = lHours;
													}

													// 结束分钟-减去应出勤分钟
													long ly = attendenceHoursTime - endTimeTime;

													BigDecimal leaveearly = new BigDecimal(ly);

													// 判断应出勤分钟是否等于实际出勤分钟
													if (attendenceHoursTime == endTimeTime) {
														if (attendance.getAttendanceState() != 2
																&& attendance.getAttendanceState() != 5) {
															// 等于正常
															attendance.setAttendanceState(1);
														}
													} else if (leaveearly.intValue() <= punchTime.getEndInterval()
															&& leaveearly.intValue() > 0) {
														// 如果等于2时，并且还是早退类型为6-迟到并早退
														if (attendance.getAttendanceState() == 2) {
															// attendance.setAttendanceState(5);
														} else {
															// 如果早上为旷工
															if (attendance.getAttendanceState() == 5) {
																// 旷工
																attendance.setAttendanceState(5);
															} else {
																// 早退
																attendance.setAttendanceState(3);
															}
														}
														// 设置早退时间分钟
														attendance.setLeaveearlyHours(leaveearly);
													} else {
														// 判断是否为早退
														if (attendance.getAttendanceState() == 2) {
															// 判断结束打卡时间，是否大于打卡结束开始时间
															if (TimeUtils.compareTime(attendance.getEndTime(),
																	punchTime.getEndFromTime()) == -1) {
																// 迟到并早退
																attendance.setAttendanceState(5);
															}
														} else {
															// 判断结束打卡时间，是否大于打卡结束开始时间
															if (TimeUtils.compareTime(attendance.getEndTime(),
																	punchTime.getEndFromTime()) == -1) {
																// 迟到并早退
																attendance.setAttendanceState(5);
															}
														}
													}
												}
											}
										}
										// 判断打卡时间小于考勤打卡时间为提前打卡为正常
										else if (!timeCalendar(endTime, punchTime.getEndToTime())) {
											if (attendance.getAttendanceState() == 1) {
												// 设置考勤状态-正常
												attendance.setAttendanceState(1);
											}
										}
										// 验证时间段是否正常打卡
										/*
										 * else if (timeCalendar(endTime,
										 * punchTime.getEndFromTime(),punchTime.getEndToTime())) { if
										 * (attendance.getAttendanceState() == 1) { // 设置考勤状态-正常
										 * attendance.setAttendanceState(1); } }
										 */else {
											// 判断加班到第二天凌晨打卡，为正常出勤
											DateFormat df = new SimpleDateFormat("HH");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
											Calendar calendar = Calendar.getInstance();
											Integer hour = null;
											try {
												calendar.setTime(df.parse(endTime));
												String hourStr = (new SimpleDateFormat("HH"))
														.format(calendar.getTime());
												if (hourStr != null) {
													hour = Integer.valueOf(hourStr);
												}
											} catch (ParseException e) {
												// TODO Auto-generated catch block
												e.printStackTrace();
											}
											// 判断时间是否为凌晨打卡。0-4点区间
											if (hour != null) {
												if (hour >= 0 && hour <= 4) {
													// 正常上班
													attendance.setAttendanceState(1);
												} else {
													// 根据应出勤天数，计算应下班时间
													BigDecimal attendenceHours = attendance.getAttendenceHours()
															.multiply(new BigDecimal(60));
													// 获取应出勤分钟
													long attendenceHoursTime = attendenceHours.longValue();
													Integer munutes = 0;
													// 午休时间段,计算
													if (punchTime.getRestFromTime() != null
															&& punchTime.getRestToTime() != null) {
														munutes = TimeUtils.differMinutes(punchTime.getRestFromTime(),
																punchTime.getRestToTime());
													}

													// 获取签退分钟
													long endTimeTime = 0;
													if (attendance.getStartTime() != null
															&& attendance.getEndTime() != null) {
														// 判断早上打开时间是否早于班次打卡时间
														if (TimeUtils.compareTime(punchTime.getStartFromTime(),
																attendance.getStartTime()) == 1) {
															// 获取签退分钟
															endTimeTime = TimeUtils.differMinutes(
																	punchTime.getStartFromTime(),
																	attendance.getEndTime()) - munutes;
														} else {
															// 获取签退分钟
															endTimeTime = TimeUtils.differMinutes(
																	attendance.getStartTime(), attendance.getEndTime())
																	- munutes;
														}
													}

													// 结束分钟-减去应出勤分钟
													long ly = attendenceHoursTime - endTimeTime;

													BigDecimal leaveearly = new BigDecimal(ly);

													// 判断应出勤分钟是否等于实际出勤分钟
													if (attendenceHoursTime == endTimeTime) {
														// 等于正常
														attendance.setAttendanceState(1);
													} else if (leaveearly.intValue() <= punchTime.getEndInterval()
															&& leaveearly.intValue() > 0) {
														// 如果等于2时，并且还是早退类型为6-迟到并早退
														if (attendance.getAttendanceState() == 2) {
															// attendance.setAttendanceState(5);
														} else {
															// 如果早上为旷工
															if (attendance.getAttendanceState() == 5) {
																// 旷工
																attendance.setAttendanceState(5);
															} else {
																// 早退
																attendance.setAttendanceState(3);
															}
														}
														// 设置早退时间分钟
														attendance.setLeaveearlyHours(leaveearly);
													} else {
														// 判断是否为早退
														if (attendance.getAttendanceState() == 2) {
															// 判断结束打卡时间，是否大于打卡结束开始时间
															if (TimeUtils.compareTime(attendance.getEndTime(),
																	punchTime.getEndFromTime()) == -1) {
																// 迟到并早退
																attendance.setAttendanceState(5);
															}
														} else {
															// 判断结束打卡时间，是否大于打卡结束开始时间
															if (TimeUtils.compareTime(attendance.getEndTime(),
																	punchTime.getEndFromTime()) == -1) {
																// 迟到并早退
																attendance.setAttendanceState(5);
															}
														}
													}

													// 如果哺乳假早上没有被使用，则查看晚上打开时间是否提前早退,考勤状态不等于，查询哺乳假期
													if (lactationBean == null && attendance.getAttendanceState() != 1) {
														// 判断员工号是否存在-首位补0
														if (lactationMap.containsKey(employeeNo)) {
															// 获取对应员工的哺乳假期
															List<LactationBean> lactationList = lactationMap
																	.get(employeeNo);
															// 循环判断日期是否在，哺乳假期范围内
															for (int lai = 0; lai < lactationList.size(); lai++) {
																LactationBean lab = lactationList.get(lai);
																if (dateCalendar(attendance.getAttendanceDate(),
																		lab.getHbornStartDate(), lab.getEndDate())) {
																	lactationBean = lab;
																	break;
																}
															}
															// 查看打开时间是否在范围之内
															if (lactationBean != null) {
																// 当天打开时间减去班次打卡时间
																long time = minutesTimeCalendar(
																		punchTime.getEndToTime(),
																		attendance.getEndTime());
																// 根据哺乳假期小时乘60分钟
																Integer hours = lactationBean.getHours()
																		.multiply(new BigDecimal(60)).intValue();
																
																//判断早上打开时间是否为空
																if(attendance.getStartTime()==null){
																	attendance.setAttendanceState(5);
																}else{
																	// 判断时长是否为，根据打卡时间减去午休时间+哺乳假休息时间
																	long lHours = (TimeUtils.differMinutes(
																			attendance.getStartTime(),
																			attendance.getEndTime()) - munutes) + hours;
																	attendance.setLeaveearlyHours(new BigDecimal(0));
																	attendance.setDescription("晚上休哺乳假期");
																	if (time <= hours) {
																		if (lHours >= attendenceHoursTime) {
																			// 正常
																			attendance.setAttendanceState(1);
																		} else {
																			// 旷工
																			attendance.setAttendanceState(5);
																		}
																	} else {
																		// 结束分钟-减去应出勤分钟
																		ly = attendenceHoursTime - lHours;
																		leaveearly = new BigDecimal(ly);
																		if (leaveearly.intValue() <= punchTime
																				.getEndInterval()
																				&& leaveearly.intValue() > 0) {
																			// 早退
																			attendance.setAttendanceState(3);
																		} else {
																			attendance.setAttendanceState(5);
																		}
																	}
																}
															}
														}
													}
												}
											}
										}
									}
								}
							}
						} else {
							if (weekendType == false) {
								// 设置考勤状态-旷工
								attendance.setAttendanceState(5);
							}
						}

						// 计算实际出勤工时数
						if (attendance.getStartTime() != null && attendance.getEndTime() != null) {
							if (punchTimeMap.containsKey(punchTimeId)) {
								PunchTime punchTime = punchTimeMap.get(punchTimeId);
								long restMinutes = 0;
								// 判断午休时间是否为空
								if (punchTime.getRestFromTime() != null && punchTime.getRestToTime() != null) {
									restMinutes = minutesTimeCalendar(punchTime.getRestToTime(),
											punchTime.getRestFromTime());
								}
								// 计算分钟
								long minutes = 0;
								// 判断早上打开时间是否早于班次打卡时间
								if (TimeUtils.compareTime(punchTime.getStartFromTime(),
										attendance.getStartTime()) == 1) {
									minutes = minutesTimeCalendar(attendance.getEndTime(),
											punchTime.getStartFromTime());
								} else {
									minutes = minutesTimeCalendar(attendance.getEndTime(), attendance.getStartTime());
								}
								// 计算分钟，并减午休时间
								attendance
										.setActualHours(new BigDecimal(minutes).subtract(new BigDecimal(restMinutes)));
								// BigDecimal mia;
								// BigDecimal mib;
								// mia = new BigDecimal(minutes);
								// mib = new BigDecimal(60);
								// attendance.setActualHours(mia.divide(mib, 1,
								// RoundingMode.HALF_UP).subtract(new BigDecimal(1)));
							}
						}
					} else {
						// 因可能没有班次属于特殊情况处理
						if (attendance.getSpecialId() == null && punchTimeType == true) {
							str.append("员工号没有所属班次,");
						}
					}

					// 判断错误信息长度
					if (str.length() == new String("第" + (i + 1) + "行").length()) {
						// 判断是否为免签人员
						if (employeeIdMap.containsKey(attendance.getEmployeeId())) {
							Employee employee = employeeIdMap.get(attendance.getEmployeeId());
							// 是否为免签
							if (employee.getIsVisaWaiver() == 1) {
								attendance.setAttendanceState(1);
								attendance.setDescription("免签人员");
							}
						}
						// 判断是否为特殊情况类型
						if (attendance.getSpecialId() != null) {
							if (!requestEmployeeIdMap.containsKey(attendance.getEmployeeId())) {
								requestEmployeeIdMap.put(attendance.getEmployeeId(),attendance.getEmployeeId());
							}
							// 查询是否生成特殊情况申请考勤信息
							AttendanceExample attendanceExample = new AttendanceExample();
							attendanceExample.createCriteria()
							.andEmployeeIdEqualTo(attendance.getEmployeeId())
							.andSpecialIdEqualTo(attendance.getSpecialId());
							List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
							if (attendanceList.size() > 0) {
								// 更正打卡时间
								Attendance updateAttendance = attendanceList.get(0);
								updateAttendance.setStartTime(attendance.getStartTime());
								updateAttendance.setEndTime(attendance.getEndTime());
								updateAttendance.setUpdateTime(new Date());
								attendanceDao.updateByPrimaryKeySelective(updateAttendance);
							} else {
								// 保存
								attendanceDao.insertSelective(attendance);
							}
						} else {
							// 判断是否日期，有申请信息
							if (attendance.getAttendanceDate() != null) {
								if (requestMap.containsKey(attendance.getEmployeeId())) {
									// 判断员工所属日期范围
									List<Request> rList = requestMap.get(attendance.getEmployeeId());
									Request request = null;
									for (int ri = 0; ri < rList.size(); ri++) {
										if (dateCalendar(attendance.getAttendanceDate(), rList.get(ri).getStartDate(),rList.get(ri).getEndDate())) {
											request = rList.get(ri);
											break;
										}
									}
									// 判断请假类型，以小时，天
									if (request != null) {
										if (!requestEmployeeIdMap.containsKey(attendance.getEmployeeId())) {
											requestEmployeeIdMap.put(attendance.getEmployeeId(),attendance.getEmployeeId());
										}
									}
								}
							}
							// 查询是否日期和人员ID是否已经导入
							AttendanceExample attendanceExample = new AttendanceExample();
							attendanceExample.createCriteria()
							.andEmployeeIdEqualTo(attendance.getEmployeeId())
							.andAttendanceDateEqualTo(attendance.getAttendanceDate());
							List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
							if (attendanceList.size() > 0) {
								//判断是否有请假操作
								if (!requestEmployeeIdMap.containsKey(attendance.getEmployeeId())) {
									requestEmployeeIdMap.put(attendance.getEmployeeId(), attendance.getEmployeeId());
								}
								attendance.setAttendanceId(attendanceList.get(0).getAttendanceId());
								attendance.setIsApprovaled(attendanceList.get(0).getIsApprovaled());
								attendance.setIsRepaired(attendanceList.get(0).getIsRepaired());
								attendance.setSpecialId(attendanceList.get(0).getSpecialId());
								attendance.setDescription(attendanceList.get(0).getDescription());
								attendance.setCreateTime(attendanceList.get(0).getCreateTime());
								attendance.setUpdateTime(new Date());
								attendanceDao.updateByPrimaryKey(attendance);
							} else {
								// 保存
								attendanceDao.insertSelective(attendance);
							}
						}
					} else {
						String errorStr = str.toString().substring(0, str.toString().length() - 1);
						errorMsgList.add(errorStr);
					}
				}

				if (errorMsgList.size() > 0) {
					throw new ResultFaultException("8_00002", errorMsgList);
				}

				Date startDate = null;
				Date endDate = null;
				// 循环日期判断最大日期和最小日期
				for (Map.Entry<Date, Date> entry : attendanceDateMap.entrySet()) {
					if (startDate == null && endDate == null) {
						startDate = entry.getValue();
						endDate = entry.getValue();
					}
					if (entry.getValue().getTime() > startDate.getTime()) {
						startDate = entry.getValue();
					}
					if (entry.getValue().getTime() < endDate.getTime()) {
						endDate = entry.getValue();
					}
				}
				// 循环人员ID
				for (Map.Entry<Integer, Integer> entry : requestEmployeeIdMap.entrySet()) {
					requestEmployeeIdList.add(entry.getValue());
				}
				
				//查询补签信息
				List<Integer> retroactiveList=retroactiveExtDao.getEmployeeIdRetroactive(employeeIdList, endDate,startDate);
				if(retroactiveList.size()>0){
					for(int ri=0;ri<retroactiveList.size();ri++){
						//判断是否有请假操作
						if (!requestEmployeeIdMap.containsKey(retroactiveList.get(ri))) {
							requestEmployeeIdMap.put(retroactiveList.get(ri), retroactiveList.get(ri));
						}
					}
				}
				
				// 生成旷工人员考勤信息
				this.addNotAttendanceDate(attendanceDateMap, employeeIdList, employeeSchedulMap, schedulDayKeyMap,punchTimeMap);
			
				// 判断是否有重新计算
				//if (requestEmployeeIdList.size() > 0) {
					//approvalService.resetAttendance(endDate, startDate, requestEmployeeIdList);
					approvalService.resetAttendance(endDate, startDate, null);
				//}

				successList.add(0, "考勤信息导入完成。");
				return successList;
			}
		}
		throw new ResultFaultException("0_00014");
	}

	/**
	 * 生成旷工人员考勤信息
	 * 
	 * @param attendanceDateMap
	 * @param employeeIdList
	 * @param employeeSchedulMap
	 * @param schedulDayKeyMap
	 * @param punchTimeMap
	 */
	@Override
	public void addNotAttendanceDate(Map<Date, Date> attendanceDateMap, List<Integer> employeeIdList,
			Map<Integer, List<EmployeeSchedul>> employeeSchedulMap, Map<Integer, List<SchedulDayKey>> schedulDayKeyMap,
			Map<Integer, PunchTime> punchTimeMap) {
		// 根据考勤导入日期生成未打卡的人员信息
		for (Map.Entry<Date, Date> entry : attendanceDateMap.entrySet()) {
			List<AttendanceBean> attendanceBeanList = attendanceExtDao.getAttendanceDateNotList(entry.getValue(),
					employeeIdList);
			for (int j = 0; j < attendanceBeanList.size(); j++) {
				// 需要验证日期是否为星期六，星期天
				Integer swId = null;
				// 判断员工和班次关系是否存在
				if (employeeSchedulMap.containsKey(attendanceBeanList.get(j).getEmployeeId())) {
					// 判断员工所属日期范围
					List<EmployeeSchedul> eList = employeeSchedulMap.get(attendanceBeanList.get(j).getEmployeeId());
					// 循环判断日期范围是否匹配
					for (int ei = 0; ei < eList.size(); ei++) {
						EmployeeSchedul employeeSchedul = eList.get(ei);
						// 验证日期是否在区间内
						if (dateCalendar(entry.getValue(), employeeSchedul.getFromDate(),
								employeeSchedul.getThruDate())) {
							swId = employeeSchedul.getSwId();
							break;
						}
					}
				}
				// 班次ID不能空时，查询班次下的日期，比对是否有上班日
				if (swId != null) {
					if (schedulDayKeyMap.containsKey(swId)) {
						boolean type = false;
						// 验证日期是否相等
						List<SchedulDayKey> schedulDayList = schedulDayKeyMap.get(swId);
						for (int sci = 0; sci < schedulDayList.size(); sci++) {
							if (schedulDayList.get(sci).getSdDate().equals(entry.getValue())) {
								type = true;
								break;
							}
						}
						if (type) {
							Attendance addAttendance = new Attendance();
							addAttendance.setEmployeeId(attendanceBeanList.get(j).getEmployeeId());
							Integer punchTimeId = null;
							// 判断员工和班次关系是否存在
							if (employeeSchedulMap.containsKey(addAttendance.getEmployeeId())) {
								// 判断员工所属日期范围
								List<EmployeeSchedul> eList = employeeSchedulMap.get(addAttendance.getEmployeeId());
								// 循环判断日期范围是否匹配
								for (int ei = 0; ei < eList.size(); ei++) {
									EmployeeSchedul employeeSchedul = eList.get(ei);
									// 验证日期是否在区间内
									if (dateCalendar(entry.getValue(), employeeSchedul.getFromDate(),
											employeeSchedul.getThruDate())) {
										punchTimeId = employeeSchedul.getPunchTimeId();
										break;
									}
								}
							}
							// 计算应出勤时间
							if (punchTimeMap.containsKey(punchTimeId)) {
								PunchTime punchTime = punchTimeMap.get(punchTimeId);
								// 计算分钟
								long minutes = minutesTimeCalendar(punchTime.getEndToTime(),
										punchTime.getStartToTime());
								BigDecimal mia;
								BigDecimal mib;
								mia = new BigDecimal(minutes);
								mib = new BigDecimal(60);
								addAttendance.setAttendenceHours(
										mia.divide(mib, 1, RoundingMode.HALF_UP).subtract(new BigDecimal(1)));
							}

							addAttendance.setAttendanceDate(entry.getValue());

							// 查看是否为免签人员
							if (attendanceBeanList.get(j).getIsVisaWaiver() == 1) {
								addAttendance.setAttendanceState(1);
								addAttendance.setDescription("免签人员");
							} else {
								addAttendance.setAttendanceState(5);
							}
							// 保存
							attendanceDao.insertSelective(addAttendance);
						}
					}
				}
			}
		}
	}

	/**
	 * 生成免签人员考勤信息
	 */
	@Override
	public boolean saveEmployeeIsVisaWaiverAttendance() {
		// 获取系统日期
		Date attendanceDate = new Date();
		// 查询考勤打卡表，默认打卡信息
		PunchTimeExample punchTimeExample = new PunchTimeExample();
		punchTimeExample.createCriteria().andIsDefaultEqualTo(1);
		List<PunchTime> punchTimeList = punchTimeDao.selectByExample(punchTimeExample);
		PunchTime punchTime = null;
		if (punchTimeList.size() > 0) {
			punchTime = punchTimeList.get(0);
		}
		// 查询人员表
		EmployeeExample employeeExample = new EmployeeExample();
		employeeExample.createCriteria().andEmployeeIsSeparatedEqualTo(0).andIsVisaWaiverEqualTo(1);
		List<Employee> employeeList = employeeDao.selectByExample(employeeExample);
		for (int i = 0; i < employeeList.size(); i++) {
			Attendance attendance = new Attendance();
			attendance.setEmployeeId(employeeList.get(i).getEmployeeId());
			attendance.setAttendanceDate(attendanceDate);
			if (punchTime != null) {
				attendance.setStartTime(punchTime.getStartToTime());
				attendance.setEndTime(punchTime.getEndToTime());
			}
			attendance.setAttendanceState(1);
			attendance.setAttendenceHours(new BigDecimal(8));
			attendance.setActualHours(new BigDecimal(8));
			attendance.setLateHours(new BigDecimal(0));
			attendance.setLeaveearlyHours(new BigDecimal(0));
			attendanceDao.insertSelective(attendance);
		}
		return true;
	}

	/**
	 * 判断time是否在from，to之内
	 * 
	 * @param time
	 *            指定日期
	 * @param from
	 *            开始日期
	 * @param to
	 *            结束日期
	 * @return
	 */
	public boolean dateCalendar(Date time, Date from, Date to) {
		Calendar date = Calendar.getInstance();
		date.setTime(time);
		Calendar after = Calendar.getInstance();
		after.setTime(from);
		Calendar before = Calendar.getInstance();
		before.setTime(to);
		if (date.getTime().compareTo(after.getTime()) >= 0 && date.getTime().compareTo(before.getTime()) <= 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 判断time是否在from之内
	 * 
	 * @param time
	 * @param from
	 * @return
	 */
	public boolean dateCalendar(Date time, Date from) {
		Calendar date = Calendar.getInstance();
		date.setTime(time);
		Calendar after = Calendar.getInstance();
		after.setTime(from);
		if (date.getTime().compareTo(after.getTime()) >= 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 时间比较大小
	 * 
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public boolean timeCalendar(String startTime, String endTime) {
		boolean type = false;
		DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
		try {
			Date dt1 = df.parse(startTime);// 将字符串转换为date类型
			Date dt2 = df.parse(endTime);
			if (dt1.getTime() <= dt2.getTime()) { // 比较时间大小,如果dt1大于dt2
				type = true;
			} else {
				type = false;
			}
		} catch (ParseException e) {
			type = false;
		}
		return type;
	}

	/**
	 * 判断是否是否为周末
	 * 
	 * @param cal
	 * @return
	 */
	private boolean isWeekend(Calendar cal) {
		int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (week == 6 || week == 0) {// 0代表周日，6代表周六
			return true;
		}
		return false;
	}

	/**
	 * 判断time是否在from，to之内
	 * 
	 * @param time
	 *            指定日期
	 * @param from
	 *            开始日期
	 * @param to
	 *            结束日期
	 * @return
	 */
	public boolean timeCalendar(String time, String from, String to) {
		boolean type = false;
		try {
			DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
			Calendar date = Calendar.getInstance();
			date.setTime(df.parse(time));
			Calendar after = Calendar.getInstance();
			after.setTime(df.parse(from));
			Calendar before = Calendar.getInstance();
			before.setTime(df.parse(to));
			if (date.getTime().compareTo(after.getTime()) >= 0 && date.getTime().compareTo(before.getTime()) <= 0) {
				type = true;
			} else {
				type = false;
			}
		} catch (ParseException e) {
			type = false;
		}
		return type;
	}

	/**
	 * 验证时间间隔
	 * 
	 * @param time
	 * @param from
	 * @param to
	 * @return
	 */
	public long minutesTimeCalendar(String from, String to) {
		long minutes = 0;
		try {
			DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
			Calendar after = Calendar.getInstance();
			after.setTime(df.parse(from));
			Calendar before = Calendar.getInstance();
			before.setTime(df.parse(to));
			minutes = (after.getTime().getTime() - before.getTime().getTime()) / (1000 * 60);
		} catch (ParseException e) {
			minutes = 0;
		}
		return minutes;
	}

	/**
	 * 返回分钟数据
	 * 
	 * @param from
	 * @return
	 */
	public long minutesTimeCalendar(String from) {
		long minutes = 0;
		try {
			DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
			Calendar after = Calendar.getInstance();
			after.setTime(df.parse(from));
			minutes = (after.getTime().getTime()) / (1000 * 60);
		} catch (ParseException e) {
			minutes = 0;
		}
		return minutes;
	}

	/**
	 * 获取人员考勤数据次数
	 * 
	 * @param emploueeId
	 * @param date
	 * @return
	 */
	@Override
	public Integer getAttendanceCount(Integer employeeId, Date date) {
		AttendanceExample attendanceExample = new AttendanceExample();
		attendanceExample.or().andEmployeeIdEqualTo(employeeId).andAttendanceDateEqualTo(date).andEndTimeIsNotNull();
		attendanceExample.or().andEmployeeIdEqualTo(employeeId).andAttendanceDateEqualTo(date).andStartTimeIsNotNull();
		return attendanceDao.countByExample(attendanceExample);
	}

	/**
	 * 根据考勤Id来获取当前日期的所有申请
	 * 
	 * @param AttendanceId
	 * @return
	 */
	@Override
	public List<RequestSelectBean> getAttendanceRight(AttendanceBean attendanceBean) {
		// 设置返回列表
		List<RequestSelectBean> requestSelectBeanList = new ArrayList<RequestSelectBean>();
		Map<Integer, String> typeMap = new HashMap<Integer, String>();
		DictionaryExample dictionaryExample = new DictionaryExample();
		dictionaryExample.createCriteria().andDicClsEqualTo("4");
		List<Dictionary> dictionaryList = dictionaryDao.selectByExample(dictionaryExample);
		for (int i = 0; i < dictionaryList.size(); i++) {
			typeMap.put(Integer.valueOf(dictionaryList.get(i).getDicCd()), dictionaryList.get(i).getDicName());
		}
		
		EmployeeExample employeeExample = new EmployeeExample();
		employeeExample.createCriteria().andEmployeeNoEqualTo(attendanceBean.getEmployeeNo());
		List<Employee> employeeList = employeeDao.selectByExample(employeeExample);
		
		// 获取Request请求类型
		RequestExample requestExample = new RequestExample();
		requestExample.createCriteria().andEmployeeIdEqualTo(employeeList.get(0).getEmployeeId())
		.andStartDateLessThanOrEqualTo(attendanceBean.getAttendanceDate())
		.andEndDateGreaterThanOrEqualTo(attendanceBean.getAttendanceDate())
		.andApprovalStateNotEqualTo(0);//未提交的不显示
		List<Request> requestList = requestDao.selectByExample(requestExample);
		for (int i = 0; i < requestList.size(); i++) {
			RequestSelectBean requestSelectBean = new RequestSelectBean();
			requestSelectBean.setStartDate(requestList.get(i).getStartDate());
			requestSelectBean.setStartTime(requestList.get(i).getStartTime());
			requestSelectBean.setStartToTime(requestList.get(i).getStartToTime());
			requestSelectBean.setEndDate(requestList.get(i).getEndDate());
			requestSelectBean.setEndTime(requestList.get(i).getEndTime());
			requestSelectBean.setRequestType(typeMap.get(requestList.get(i).getRequestType()));
			requestSelectBean.setMarryDate(requestList.get(i).getMarryDate());
			requestSelectBean.setRequestDate(requestList.get(i).getRequestDate());
			requestSelectBean.setRequestId(requestList.get(i).getRequestId());
			requestSelectBeanList.add(requestSelectBean);
		}
		return requestSelectBeanList;
	}

	/**
	 * 根据考勤Id来撤回补签信息
	 * 
	 * @param attendanceId
	 * @param type
	 * @return
	 */
	@Override
	public boolean retractAttednance(Integer attendanceId, Integer type) {
		Retroactive retroactive=null;
		//查询考勤信息，是否已经
		RetroactiveExample retroactiveExample = new RetroactiveExample();
		retroactiveExample.setOrderByClause("create_time desc");
		List<Retroactive> retroactivesList = new ArrayList<Retroactive>();
		ApprovalRecordExample approvalRecordExample = new ApprovalRecordExample();
		if (type == 0) { 
			retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId).andEndTimeIsNull();
			retroactivesList = retroactiveDao.selectByExample(retroactiveExample);
		} else {
			retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId).andStartTimeIsNull();
			retroactivesList = retroactiveDao.selectByExample(retroactiveExample);
		}
		//判断是否已经审批过
		if(retroactivesList.size()>0){
			retroactive=retroactivesList.get(0);
			if(retroactivesList.get(0).getApprovalState()==2 
					|| retroactivesList.get(0).getApprovalState()==3){
				throw new ResultFaultException("4_00019");
			}
		}
		
		//请求BPM系统撤回		
		if(bpmService.revokeBPM(null, retroactive, retroactive.getEmployeeId(), "hr003")) {
			for (int i = 0; i < retroactivesList.size(); i++) {
				int retroactiveId = retroactivesList.get(i).getRetroactiveId();
				approvalRecordExample.createCriteria().andRetroactiveIdEqualTo(retroactiveId);
				retroactiveDao.deleteByPrimaryKey(retroactiveId);
				approvalRecordDao.deleteByExample(approvalRecordExample);
			}
			
			RetroactiveExample retroactiveExample2 = new RetroactiveExample();
			retroactiveExample2.createCriteria().andAttendanceIdEqualTo(attendanceId);
			retroactivesList = retroactiveDao.selectByExample(retroactiveExample2);
			Attendance attendance = new Attendance();
			attendance.setAttendanceId(attendanceId);
			if (retroactivesList.size() > 0) {
				Integer approvalState = retroactivesList.get(0).getApprovalState();
				attendanceDao.selectByPrimaryKey(attendanceId).setIsRepaired(approvalState);
				attendance.setIsApprovaled(approvalState);
				attendance.setIsRepaired(approvalState);
			} else {
				attendance.setIsApprovaled(0);
				attendance.setIsRepaired(0);
			}
			attendanceDao.updateByPrimaryKeySelective(attendance);
		}	
		return true;
	}

	/**
	 * 获取原始打卡时by日期
	 */
	@Override
	public AttendanceBean getAttendanceTimeByDate(AttendanceBean attendanceBean) {
		AttendanceExample attendanceExample = new AttendanceExample();
		attendanceExample.createCriteria().andAttendanceDateEqualTo(attendanceBean.getAttendanceDate())
		.andEmployeeIdEqualTo(attendanceBean.getEmployeeId());
		
		List<Attendance> attList = attendanceDao.selectByExample(attendanceExample);
		if (attList.size()>0) {
			attendanceBean.setOriginalStartTime(attList.get(0).getOriginalStartTime());
			attendanceBean.setOriginalEndTime(attList.get(0).getOriginalEndTime());
		}
		return attendanceBean;
	}

}
